package com.itheima.core.utils;


import com.itheima.core.domain.Configuration;

import javax.sql.DataSource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 执行器的类，专门用于执行SQL语句
 *
 * @author Administrator
 */
public class Executor {
    private Configuration cfg;

    public Executor(Configuration cfg) {
        this.cfg = cfg;
    }

    //执行的是查询语句
    public <E> List<E> executeQuery(String sql, String resultType) throws Exception {
        //1.获取连接
        Connection conn = null;
        try {
            Class.forName(cfg.getDriver());
            conn = DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            //2.创建预编译执行者对象
            pst = conn.prepareStatement(sql);
            //3.执行sql,并获取结果集
            rs = pst.executeQuery();
            //4.处理结果集
            //获取元数据
            ResultSetMetaData metaData = rs.getMetaData();
            //获取列数
            int columnCount = metaData.getColumnCount();
            List list = new ArrayList();
            while (rs.next()) {
                //获取封装一条记录的对象
                Class<?> clazz = Class.forName(resultType);
                Object obj = clazz.newInstance();
                //遍历每一个字段的名和值
                for (int i = 1; i <= columnCount; i++) {
                    //获取字段名
                    String columnName = metaData.getColumnName(i);
                    //获取字段值
                    Object columnValue = rs.getObject(i);
                    //获取对象的每一个方法
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        if (("set" + columnName).equalsIgnoreCase(method.getName())) {
                            method.invoke(obj, columnValue);
                        }
                    }

                }
                list.add(obj);
            }
            return list;
        } finally {
            rs.close();
            pst.close();
            conn.close();
        }
    }

    /**
     * 还可以定义执行更新的方法，这样就可以完成新增，更新，保存操作
     */
    public int executeUpdate(String sql, String... params) {
        //此处省略。。。。。
        return 0;
    }
}
